﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Foxit.PDF;
using Foxit.PDF.IO;
using Foxit.PDF.PageElements;
using Sustainalytics.Reporting.Framework;

namespace Sustainalytics.RiskRatings.Reporting.Charts
{
    public enum RiskRangeChartType
    {
        OverallRiskDetails,
        IssueRiskDetails,
    }
    public class RiskRating_RiskRangeBarChart : PageElement
    {
        public float Left { get; set; }
        public float Top { get; set; }
        public float Width { get; set; }
        public double Value1 { get; set; }
        public double Value2 { get; set; }
        public double Value3 { get; set; }
        public double Value4 { get; set; }
        public double Value5 { get; set; }
        public double Value6 { get; set; }
        public float BarHeight { get; set; }
        public RiskRangeChartType ChartType { get; set; }
        public float LeftBar { get; set; }
        public float TopBar { get; set; }

        private Group _elements;
        public void Render()
        {
            _elements = Elements();
        }

        private Group Elements()
        {
            var elements = new Group();
            float currentYOffset = Top;
            float startPos = Left - 10f;
            float chartMaxWidth = Width * 0.55f;
            float dotSize = chartMaxWidth / (float)Math.Max(Value1, Value2);
            float pageWidth = 545f;
            float textWidth = 250f;
            float textHeight = 200f;
            var lineColor = new RgbColor(112, 112, 112);


            var style = new FormattedTextAreaStyle(Fonts.RobotoFontFamily, 5.5f, false)
            {
                Paragraph = { Align = TextAlign.Justify, Indent = 0, SpacingAfter = 0, AllowOrphanLines = false }
            };

            var companyExposureText = "The company’s sensitivity or vulnerability to ESG risks.";
            var manageableRiskText = "Material ESG risk that can be influenced and managed through suitable policies, programmes and initiatives. ";
            var managedRiskText = "Material ESG risk that has been managed by a company through suitable policies, programmes or initiatives.";
            var managementGapText = "Measures the difference between material ESG risk that could be managed by the company and what the company is managing.";
            var unmanageableRiskText = "Material ESG risk inherent in the products or services of a company and/or the nature of a company’s business, which cannot be managed by the company.";
            var totalUnmanagedRiskText = " Material ESG risk that has not been managed by a company, and includes two types of risk: unmanageable risk, as well as risks that could be managed by a company through suitable initiatives but which may not yet be managed.";

            string firstBarText = string.Empty, secondBarText = string.Empty, thirdBarText = string.Empty, fourthBarText = string.Empty,
                fifthBarText = String.Empty, sixthBarText = String.Empty;
            RgbColor firstBarColor = RgbColor.Black, secondBarColor = RgbColor.Black, thirdBarColor = RgbColor.Black, sixthBarColor = RgbColor.Black;
            float firstBarVerticalGap = BarHeight, secondBarVerticalGap = BarHeight;


            firstBarText = "Company Exposure";
            secondBarText = "Manageable Risk";
            thirdBarText = "Managed Risk";
            fourthBarText = "Management Gap";
            fifthBarText = "Unmanageable Risk";
            sixthBarText = (ChartType == RiskRangeChartType.OverallRiskDetails? "Overall" : "Issue") + " Unmanaged Risk";
            firstBarColor = new RgbColor(255, 153, 0);
            secondBarColor = new RgbColor(183, 196, 46);
            thirdBarColor = new RgbColor(219, 225, 150);
            sixthBarColor = new RgbColor(108, 111, 112);
            firstBarVerticalGap = BarHeight / 2;
            secondBarVerticalGap = BarHeight * 1.5f;

            ////add Guidance label
            //elements.Add(new Label("Guidance",
            //      startPos + 140f + (float)Value1 * dotSize + 15f,
            //      currentYOffset -25f,
            //      50f,
            //      7f, Fonts.RobotoBold, 7f, TextAlign.Left, RgbColor.Black));

            //add line before first bar
            elements.Add(new Line(startPos + 5f,
                          currentYOffset - 15f,
                          pageWidth,
                          currentYOffset - 15f,
                          0.5f, lineColor));
            //Exposure label
            elements.Add(new Label("Exposure",
                        startPos + 5f,
                        currentYOffset - 13,
                        50f,
                        7f, Fonts.RobotoBold, 7f, TextAlign.Left, RgbColor.Black));
            // first bar
            elements.Add(new TextArea(firstBarText,
                            Left + 20f,
                            currentYOffset - 3,
                            Width * 0.45f,
                            20f, Fonts.RobotoRegular, 7f, TextAlign.Right, RgbColor.Black));

            elements.Add(new Label(Value1.ToString("0.0"),
                            Left + 100f,
                            currentYOffset - 3,
                            Width * 0.20f,
                            7f, Fonts.RobotoRegular, 7f, TextAlign.Center, RgbColor.Black));

            elements.Add(new Line(startPos + 140f,
                            currentYOffset + 3f,
                            startPos + 140f + (float)Value1 * dotSize,
                            currentYOffset + 3f,
                            BarHeight,
                            firstBarColor));

            elements.Add(new FormattedTextArea(companyExposureText,
                            startPos + 140f + (float)Value1 * dotSize + 15f,
                            currentYOffset - 3,
                            250f,
                            200f,
                            style));

            var xExposure = startPos + 140f;
            var yExposure = currentYOffset + 3f;
            //currentYOffset += BarHeight + firstBarVerticalGap + 45f;

            currentYOffset += BarHeight + firstBarVerticalGap + 15f;
            //add line after first bar
            elements.Add(new Line(startPos + 5f,
                            currentYOffset - 10f,
                            pageWidth,
                            currentYOffset - 10f,
                            0.5f, lineColor));
            elements.Add(new Label("Management",
                    startPos + 5f,
                    currentYOffset - 8,
                    50f,
                    7f, Fonts.RobotoBold, 7f, TextAlign.Left, RgbColor.Black));
            currentYOffset += 5f;
            // second bar
            elements.Add(new TextArea(secondBarText,
                             Left + 20f,
                             currentYOffset - 3,
                             Width * 0.45f,
                             20f, Fonts.RobotoRegular, 7f, TextAlign.Right, RgbColor.Black));

            elements.Add(new Label(Value2.ToString("0.0"),
                            Left + 100f,
                            currentYOffset - 3,
                            Width * 0.20f,
                            7f, Fonts.RobotoRegular, 7f, TextAlign.Center, RgbColor.Black));

            elements.Add(new Line(startPos + 140f,
                            currentYOffset + 3f,
                            startPos + 140f + (float)Value2 * dotSize,
                            currentYOffset + 3f,
                            BarHeight,
                            secondBarColor));

            var xManageableRisk = startPos + 140f + (float)Value2 * dotSize;
            var yManageableRisk = currentYOffset + 3f;

            elements.Add(new FormattedTextArea(manageableRiskText,
                            startPos + 140f + (float)Value1 * dotSize + 15f,
                            currentYOffset - 3f,
                            textWidth,
                            textHeight,
                            style));
            currentYOffset += BarHeight + firstBarVerticalGap + 20f;
            elements.Add(new Line(startPos + 140f + (float)Value1 * dotSize + 15f, currentYOffset - 10f, pageWidth, currentYOffset - 10f, 0.5f, RgbColor.Black, LineStyle.Solid));

            //third bar
            elements.Add(new TextArea(thirdBarText,
                            Left + 20f,
                            currentYOffset - 3,
                            Width * 0.45f,
                            20f, Fonts.RobotoRegular, 7f, TextAlign.Right, RgbColor.Black));

            elements.Add(new Label(Value3.ToString("0.0"),
                            Left + 100f,
                            currentYOffset - 3,
                            Width * 0.20f,
                            7f, Fonts.RobotoRegular, 7f, TextAlign.Center, RgbColor.Black));

            elements.Add(new Line(startPos + 140f,
                            currentYOffset,
                            startPos + 140f + (float)Value3 * dotSize,
                            currentYOffset,
                            BarHeight,
                            thirdBarColor));
            var yManagedRisk = currentYOffset;

            elements.Add(new FormattedTextArea(managedRiskText,
                            startPos + 140f + (float)Value1 * dotSize + 15f,
                            currentYOffset - 3f,
                            textWidth,
                            textHeight,
                            style));

            currentYOffset += BarHeight + secondBarVerticalGap + 10f;

            elements.Add(new Line(startPos + 140f + (float)Value1 * dotSize + 15f,
                            currentYOffset - 10f,
                            pageWidth,
                            currentYOffset - 10f,
                            0.5f,
                            RgbColor.Black,
                            LineStyle.Solid));

            //fourth bar
            elements.Add(new TextArea(fourthBarText,
                            Left + 20f,
                            currentYOffset - 3,
                            Width * 0.45f,
                            20f, Fonts.RobotoRegular, 7f, TextAlign.Right, RgbColor.Black));

            elements.Add(new Label(Value4.ToString("0.0"),
                            Left + 100f,
                            currentYOffset - 3,
                            Width * 0.20f,
                            7f, Fonts.RobotoRegular, 7f, TextAlign.Center, RgbColor.Black));

            elements.Add(new Line(startPos + 140f + (float)Value3 * dotSize,
                            currentYOffset + 3f,
                            startPos + 140f + (float)Value2 * dotSize,
                            currentYOffset + 3f,
                            BarHeight,
                            thirdBarColor));

            //var yManagementGap = currentYOffset + 3f;

            elements.Add(new FormattedTextArea(managementGapText,
                            startPos + 140f + (float)Value1 * dotSize + 15f,
                            currentYOffset - 3f,
                            textWidth,
                            textHeight,
                            style));

            currentYOffset += BarHeight + secondBarVerticalGap + 10f;

            elements.Add(new Line(startPos + 140f + (float)Value1 * dotSize + 15f,
                            currentYOffset - 10f,
                            pageWidth,
                            currentYOffset - 10f,
                            0.5f,
                            RgbColor.Black,
                            LineStyle.Solid));

            //fifth bar
            elements.Add(new TextArea(fifthBarText,
                            Left + 20f,
                            currentYOffset - 3,
                            Width * 0.45f,
                            20f, Fonts.RobotoRegular, 7f, TextAlign.Right, RgbColor.Black));

            elements.Add(new Label(Value5.ToString("0.0"),
                            Left + 100f,
                            currentYOffset - 3,
                            Width * 0.20f,
                            7f, Fonts.RobotoRegular, 7f, TextAlign.Center, RgbColor.Black));

            elements.Add(new Line(startPos + 140f + (float)Value2 * dotSize,
                            currentYOffset + 3f,
                            startPos + 140f + (float)Value1 * dotSize,
                            currentYOffset + 3f, BarHeight, thirdBarColor));

            elements.Add(new FormattedTextArea(unmanageableRiskText,
                            startPos + 140f + (float)Value1 * dotSize + 15f,
                            currentYOffset - 3f,
                            textWidth,
                            textHeight,
                            style));

            var xUnmanageableRisk = startPos + 140f + (float)Value2 * dotSize;
            var yUnmanageableRisk = currentYOffset + 3f;

            currentYOffset += BarHeight + secondBarVerticalGap + 10f;
            elements.Add(new Line(startPos + 5f,
                      currentYOffset - 15f,
                      pageWidth,
                      currentYOffset - 15f,
                      0.5f, lineColor));
            //sixth bar
            elements.Add(new Line(startPos + 5f,
                        currentYOffset + 5f,
                        pageWidth,
                        currentYOffset + 5f,
                        40f, new RgbColor(235, 241, 246)));
            elements.Add(new Label("ESG Risk Rating",
                        startPos + 5f,
                        currentYOffset - 15f,
                        70f,
                        7f, Fonts.RobotoBold, 7f, TextAlign.Left, RgbColor.Black));
            elements.Add(new TextArea(sixthBarText,
                          Left + 20f,
                          currentYOffset - 3,
                          Width * 0.45f,
                          20f, Fonts.RobotoRegular, 7f, TextAlign.Right, RgbColor.Black));

            elements.Add(new Label(Value6.ToString("0.0"),
                            Left + 100f,
                            currentYOffset - 3,
                            Width * 0.20f,
                            7f, Fonts.RobotoRegular, 7f, TextAlign.Center, RgbColor.Black));

            elements.Add(new Line(startPos + 140f + (float)Value3 * dotSize,
                            currentYOffset + 3f,
                            startPos + 140f + (float)Value1 * dotSize,
                            currentYOffset + 3f,
                            BarHeight,
                            sixthBarColor));
            var yUnmanagedRisk = currentYOffset + 3f;
            elements.Add(new FormattedTextArea(totalUnmanagedRiskText,
                            startPos + 140f + (float)Value1 * dotSize + 15f,
                            currentYOffset - 3f,
                            textWidth,
                            textHeight,
                            style));


            //adding the four lines of the chart
            elements.Add(new Line(xExposure,
                             yExposure - (BarHeight / 2),
                             xExposure,
                             currentYOffset + (BarHeight / 2) + 3f,
                             0.5f, lineColor));

            elements.Add(new Line(startPos + 140f + (float)Value1 * dotSize,
                            yExposure - (BarHeight / 2),
                            startPos + 140f + (float)Value1 * dotSize,
                            yUnmanagedRisk + (BarHeight / 2),
                            0.5f, lineColor));

            elements.Add(new Line(startPos + 140f + (float)Value3 * dotSize,
                            //yManagementGap - (BarHeight / 2),
                            yManagedRisk - (BarHeight / 2),
                            startPos + 140f + (float)Value3 * dotSize,
                            currentYOffset + 3f + (BarHeight / 2),
                            0.5f, lineColor));

            elements.Add(new Line(xManageableRisk,
                            yManageableRisk - (BarHeight / 2),
                            xUnmanageableRisk,
                            yUnmanageableRisk + (BarHeight / 2),
                            0.5f, lineColor));

            return elements;
        }

        public override void Draw(PageWriter writer)
        {
            if (_elements == null)
                Render();

            writer.Write_q_(true);
            _elements.Draw(writer);
            writer.Write_Q(true);
        }
    }
}
